package com.lzj.server.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lzj.server.constant.RedisConstant;
import com.lzj.server.constant.enums.RoleEnum;
import com.lzj.server.constant.enums.SystemEnum;
import com.lzj.server.entity.video.Favorite;
import com.lzj.server.entity.video.UserInfo;
import com.lzj.server.exceptions.BaseException;
import com.lzj.server.repository.mapper.AdminMapper;
import com.lzj.server.repository.mapper.FavoriteMapper;
import com.lzj.server.repository.mapper.UserMapper;
import com.lzj.server.service.UserService;
import com.lzj.server.utils.RedisUtils;
import com.lzj.server.utils.SecurityUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;

@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, UserInfo> implements UserService {
    // 默认头像附件ID
    private static final Long DEFAULT_AVATAR_ATTACHMENT_ID = 1L;

    @Resource
    private FavoriteMapper favoriteMapper;

    @Resource
    private AdminMapper adminMapper;

    @Resource
    private UserMapper userMapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean register(UserInfo user) {
        String code = user.getCode();
        String email = user.getEmail();
        boolean verified = false;
        try {
            // 1. 判断用户是否已存在
            UserInfo existUser = this.getOne(new LambdaQueryWrapper<UserInfo>()
                    .eq(UserInfo::getEmail, email));
            if (Objects.nonNull(existUser)) {
                throw new BaseException("该邮箱已被注册");
            }

            // 2. 校验验证码
            String cacheCode = RedisUtils.getObjectBean(RedisConstant.EMAIL_CODE + email, String.class);
            if (StrUtil.isBlank(cacheCode) || !code.equals(cacheCode)) {
                throw new BaseException("验证码错误或已过期");
            }else {
                verified = true;
            }
            // 3. 初始化用户
            initUser(user);
        } finally {
            // 4. 校验成功删除验证码,，没删除还有过期时间兜底
            if (verified) {
                RedisUtils.del(RedisConstant.EMAIL_CODE + email);
            }
        }
        return true;
    }

    public void initUser(UserInfo user) {
        String email = user.getEmail();
        UserInfo newUser = new UserInfo();
        newUser
                .setEmail(email)
                .setPassword(SecurityUtils.encodePassword(user.getPassword()))
                .setNickname("用户" + RandomUtil.randomNumbers(6))
                .setGender(SystemEnum.UNKNOWN.code())
                .setStatus(SystemEnum.NORMAL.code())
                .setTheme(SystemEnum.THEME.desc())
                .setAvatarAttachmentId(DEFAULT_AVATAR_ATTACHMENT_ID);
        // 1 保存用户
        if (userMapper.insert(newUser) <= 0) {
            throw new BaseException("注册失败，请稍后再试");
        }
        // 2 分配用户角色
        adminMapper.configUserRole(newUser.getId(), adminMapper.getRoleIdByCode(RoleEnum.USER.code()));
        // 2 初始化用户默认收藏夹
        Favorite favorite = new Favorite();
        favorite.setDescription("这是系统默认收藏夹");
        favorite.setIsDefault(1);
        favorite.setName("默认收藏夹");
        favorite.setUserId(newUser.getId());
        if (favoriteMapper.insert(favorite) <= 0) {
            throw new BaseException("注册失败，请稍后再试");
        }
    }

    @Override
    public boolean checkCode(String code, String email) {
        return code.equals(String.valueOf(RedisUtils.get(RedisConstant.EMAIL_CODE + email)));
    }

    @Override
    public String login(String email, String password) {
        // 判断参数是否为空
        if (StrUtil.isBlank(email) || StrUtil.isBlank(password)) {
            throw new BaseException("账号或密码不能为空");
        }
        // 查询用户 验证密码
        UserInfo user = baseMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getEmail, email));
        if (ObjUtil.isNull(user) || !SecurityUtils.matches(password, user.getPassword())) {
            throw new BaseException("账号或密码错误");
        }
        StpUtil.login(user.getId());
        return StpUtil.getTokenValue();
    }

    /**
     * 找回密码
     *
     * @param newUser 前端传来的用户信息
     * @return boolean
     */
    @Override
    public boolean findPassword(UserInfo newUser) {
        String code = newUser.getCode();
        String email = newUser.getEmail();
        String newPassword = newUser.getPassword();

        // 1. 查询验证码
        Object captcha = RedisUtils.get(RedisConstant.EMAIL_CODE + email);

        // 2. 查询用户
        UserInfo user = this.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getEmail, email));

        // 3. 校验逻辑拆解更明确
        if (Objects.isNull(user)) {
            throw new BaseException("该邮箱未注册");
        }
        if (Objects.isNull(captcha)) {
            throw new BaseException("验证码已失效，请重新获取");
        }
        if (!code.equals(String.valueOf(captcha))) {
            throw new BaseException("验证码错误");
        }

        // 4. 更新密码（请确保 encodePassword 是安全加密方式）
        this.update(new LambdaUpdateWrapper<UserInfo>()
                .eq(UserInfo::getEmail, email)
                .set(UserInfo::getPassword, SecurityUtils.encodePassword(newPassword)));

        // 5. 删除验证码，防止重用
        RedisUtils.del(RedisConstant.EMAIL_CODE + email);

        return true;
    }

}

